<?php

namespace app\admin\model;

use EasyWeChat\Factory;
use EasyWeChat\Kernel\Exceptions\HttpException;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use EasyWeChat\Kernel\Exceptions\RuntimeException;
use EasyWeChat\Payment\Jssdk\Client;
use Psr\SimpleCache\InvalidArgumentException;
use think\exception\ValidateException;

/**
 * Order
 * @controllerUrl 'wechat'
 */
class Wechat
{

    private $config;

    public function __construct()
    {
        $root = app()->getRootPath();
        $cert = parse_url(get_sys_config('merch_cert'));
        $key = parse_url(get_sys_config('merch_key'));
        $request = request();
        $this->config = [
            // 必要配置
            'app_id' => get_sys_config('routine_app_id'),
            'secret' => get_sys_config('routine_secret'),
            'mch_id' => get_sys_config('merchid'),
            'key' => get_sys_config('merchkey'),   // API v2 密钥 (注意: 是v2密钥 是v2密钥 是v2密钥)

            // 如需使用敏感接口（如退款、发送红包等）需要配置 API 证书路径(登录商户平台下载 API 证书)
            'cert_path' => $root . 'public' . $cert['path'], // XXX: 绝对路径！！！！
            'key_path' => $root . 'public' . $key['path'],      // XXX: 绝对路径！！！！

            'notify_url' => $request->scheme() . '://' . $request->host() . '/index.php/api/wechat/orderPaySuccess',
            // 你也可以在下单时单独设置来想覆盖它
            'rsa_public_key_path' => app()->getRootPath() . 'public-1632314426.pem',

            'response_type' => 'array',
            'log' => [
                'level' => 'debug',
                'file' => __DIR__ . '/wechat.log',
            ],
            // 'sandbox'       => true, // 设置为 false 或注释则关闭沙箱模式
        ];
    }

    public function payment($payBody, $orderSn, $payPrice, $openId, $channel, $type)
    {
        $app = $this->getPayment();
        if ($app->inSandbox()) {
            $payPrice = 1.01;
        }
        $url = '';
        switch ($type) {
            case 0:
                $url = url('wechat/orderPaySuccess', [], false, true)->build();
                break;
            case 1:
                $url = url('wechat/oilOrderPaySuccess', [], false, true)->build();
                break;
            case 2:
                $url = url('wechat/rechargeSuccess', [], false, true)->build();
                break;
        }
        $data = [
            'body' => $payBody,
            'out_trade_no' => $orderSn,
            'total_fee' => (int)bcmul($payPrice, 100),
            'notify_url' => $url, // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            'trade_type' => $channel == 0 ? 'JSAPI' : 'APP', // 请对应换成你的支付方式对应的值类型
            'openid' => $openId,
            'sign_type' => 'MD5',
        ];
        $data['total_fee'] = 1; // TODO 上线前取消
        $result = $app->order->unify($data);
        if ($result['return_code'] != 'SUCCESS') {
            throw new ValidateException($result['return_msg']);
        }
        if ($result['result_code'] != 'SUCCESS') {
            throw new ValidateException($result['err_code_des']);
        }
        $payment = (new Client($app))->bridgeConfig($result['prepay_id']);
        return json_decode($payment, true);
    }

    public function getPayment()
    {
        return Factory::payment($this->config);
    }

    public function getWechat()
    {
        return Factory::miniProgram($this->config);
    }

    /**
     * @return array
     * @throws HttpException
     * @throws InvalidConfigException
     * @throws RuntimeException
     * @throws InvalidArgumentException|\EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     */
    public function getAccessToken(){
        return $this->getWechat()->access_token->getToken();
    }
}